package cn.turboinfo.fuyang.api.provider.common.service.impl.product;

import cn.turboinfo.fuyang.api.domain.common.service.product.ProductSkuService;
import cn.turboinfo.fuyang.api.domain.common.service.spec.SpecService;
import cn.turboinfo.fuyang.api.entity.common.enumeration.product.ProductSkuStatus;
import cn.turboinfo.fuyang.api.entity.common.exception.product.ProductException;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.ProductSku;
import cn.turboinfo.fuyang.api.entity.common.pojo.spec.Spec;
import cn.turboinfo.fuyang.api.entity.common.pojo.spec.SpecUpdater;
import cn.turboinfo.fuyang.api.provider.common.repository.database.product.ProductSkuDAO;
import cn.turboinfo.fuyang.api.provider.common.repository.database.product.ProductSkuPO;
import cn.turboinfo.fuyang.api.provider.common.repository.database.product.ProductSkuSpecRelDAO;
import cn.turboinfo.fuyang.api.provider.common.repository.database.product.ProductSkuSpecRelPO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import net.sunshow.toolkit.core.base.enums.YesNoStatus;
import net.sunshow.toolkit.core.qbean.helper.service.impl.DefaultQServiceImpl;
import nxcloud.foundation.core.data.support.annotation.EnableSoftDelete;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@EnableSoftDelete
@Service
public class ProductSkuServiceImpl extends DefaultQServiceImpl<ProductSku, Long, ProductSkuPO, ProductSkuDAO> implements ProductSkuService {

    private final ProductSkuSpecRelDAO productSkuSpecRelDAO;

    private final SpecService specService;

    @Override
    @Transactional
    public ProductSku save(Object creator) {
        ProductSku productSku = super.save(creator);
        for (Spec spec : productSku.getSpecList()) {
            ProductSkuSpecRelPO relPO = new ProductSkuSpecRelPO();
            relPO.setProductSkuId(productSku.getId());
            relPO.setSpecId(spec.getId());

            specService.update(SpecUpdater
                    .builder(spec.getId())
                    .withAllowDelete(YesNoStatus.NO)
                    .build());

            productSkuSpecRelDAO.save(relPO);
            if (spec.getChildren() != null) {
                spec.getChildren().forEach(specChild -> {
                    ProductSkuSpecRelPO relChildPO = new ProductSkuSpecRelPO();
                    relChildPO.setProductSkuId(productSku.getId());
                    relChildPO.setSpecId(specChild.getId());
                    productSkuSpecRelDAO.save(relChildPO);
                    
                    specService.update(SpecUpdater
                            .builder(spec.getId())
                            .withAllowDelete(YesNoStatus.NO)
                            .build());
                });
            }
        }
        return productSku;
    }

    @Override
    @Transactional
    public void updateSpecList(Long productSkuId, List<Spec> specList) {
        ProductSkuPO po = getEntityWithNullCheckForUpdate(productSkuId);

        productSkuSpecRelDAO.deleteByProductSkuId(productSkuId);
        productSkuSpecRelDAO.flush();

        for (Spec spec : specList) {
            ProductSkuSpecRelPO relPO = new ProductSkuSpecRelPO();
            relPO.setProductSkuId(productSkuId);
            relPO.setSpecId(spec.getId());

            productSkuSpecRelDAO.save(relPO);
        }

        po.setSpecList(specList);
    }

    @Override
    public List<ProductSku> findSkuByProductId(Long productId) {
        return convertQBeanToList(dao.findByProductIdOrderByIdDesc(productId));
    }

    @Override
    @Transactional
    public void updateStatus(Long id, ProductSkuStatus productSkuStatus) throws ProductException {
        ProductSkuPO productSkuPO = getEntityWithNullCheckForUpdate(id, dao);
        productSkuPO.setStatus(productSkuStatus);
    }

    @Override
    @Transactional
    public void updateStatusByProduct(Long productId, ProductSkuStatus productSkuStatus) throws ProductException {
        val productSkuPOList = dao.findByProductIdOrderByIdDesc(productId);
        productSkuPOList.forEach(productSkuPO -> {
            productSkuPO.setStatus(productSkuStatus);
            dao.save(productSkuPO);
        });
    }

}
